/*
 *  This license is based on the BSD license adopted by the Apache Foundation.
 */
package Source;



import Interfaz.InfoArchivo;
import Interfaz.InterfacePeer;
import java.awt.Desktop;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import javazoom.jl.decoder.JavaLayerException;
import net.jxta.discovery.DiscoveryService;
import net.jxta.document.AdvertisementFactory;
import net.jxta.id.ID;
import net.jxta.peergroup.PeerGroup;
import net.jxta.platform.NetworkManager;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javazoom.jl.player.Player;
import net.jxta.id.IDFactory;
import net.jxta.peer.PeerID;
import net.jxta.pipe.PipeID;
import net.jxta.pipe.PipeService;
import net.jxta.protocol.PipeAdvertisement;
import net.jxta.socket.JxtaSocket;
import javax.crypto.Cipher;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import org.bouncycastle.x509.X509V3CertificateGenerator;
import source.AESEncrypter;
/**
 * Illustrates the use of Discovery Service
 * Note this is for illustration purposes and is not meant as a blue-print
 */
public final class Peer  {
   
    public static final int PUERTO = 12345;
    public static final long TAM_PAQUETES = 512;
    private String peerName;
    private String peerPassword;
    private transient NetworkManager manager;
    private transient DiscoveryService discovery;
    private transient PeerGroup netPeerGroup = null;
    private transient PipeAdvertisement pipeAdv;
    private PeerID peerID;
    public final static String SOCKETIDSTR = "urn:jxta:uuid-59616261646162614E5047205032503393B5C2F6CA7A41FBB0F890173088E79404";
    private HashMap<String, AdvertisementSharedFiles> listaTemp;
    private String busqueda;
    private String tipoBusqueda;
    private Long tamanoBusqueda;
    private HashMap<String, AdvertisementSharedFiles> listaArchivosBusqueda;
    private InterfacePeer inteface;
    private ArrayList<InfoArchivo> listaCompartidos;
    private ArrayList<InfoArchivo> listaDescargados;
    private ID idpeer;
    private TreadWaitingAccessFile threadEsperaArbrirArchivo;
    private boolean variableGlobal;
    private GuardarEstadoNodoXML guardarEstadoNodoXML;
    private int numEstado;
    private PrivateKey llavePrivada;
    private PublicKey llavePublica;
    private String llaveEntrePeers;
    private StringEncrypter encriptador;
    private AESEncrypter AESFileEncripter;
    private MensajeDigest digest;

    /**
     * Constructor for the Peer
     */
    public Peer(String peerName, String clave) throws NoSuchAlgorithmException {
        encriptador= new StringEncrypter();
        llaveEntrePeers="password";
        variableGlobal= true;
        listaTemp = new HashMap<String, AdvertisementSharedFiles>();
        listaCompartidos= new ArrayList<InfoArchivo>();
        listaDescargados= new ArrayList<InfoArchivo>();


        tipoBusqueda="NADA";
        this.peerName = peerName;
        this.peerPassword= clave;
        try {
            AdvertisementFactory.registerAdvertisementInstance(AdvertisementSharedFiles.getAdvertisementType(), new AdvertisementSharedFiles.Instantiator());
            AdvertisementFactory.registerAdvertisementInstance(AdvertisementAskForFile.getAdvertisementType(), new AdvertisementAskForFile.Instantiator());
            AdvertisementFactory.registerAdvertisementInstance(AdvertisementGuardarEstadoGlobal.getAdvertisementType(), new AdvertisementGuardarEstadoGlobal.Instantiator());
            /**ANTES*/
            manager = new NetworkManager(NetworkManager.ConfigMode.ADHOC, peerName,new File(new File(".cache"), peerName).toURI());
            manager.startNetwork();
        } catch (Exception e) {
        }
        netPeerGroup = manager.getNetPeerGroup();

         try {
            PeerServerSocket p = new PeerServerSocket(netPeerGroup);
            Thread threaduno = new Thread(p);
            threaduno.start();
            AuthenticatePeer(peerName);
           //Thread.currentThread().setName(PeerServerSocket.class.getName() + ".main()");
        } catch (Throwable e) {
            System.err.println("Failed : " + e);
            e.printStackTrace(System.err);
            System.exit(-1);
        }
        // get the discovery service
        discovery = netPeerGroup.getDiscoveryService();
        ThreadCapturaAdvertisments threCaptura = new ThreadCapturaAdvertisments(discovery, this);
        
        peerID= netPeerGroup.getPeerID();

        this.guardarEstadoNodoXML= new GuardarEstadoNodoXML();
        this.numEstado=0;
         

        /**
         * inicializar el encriptador
         */

        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);
        SecretKey key = kgen.generateKey();
        // Create encrypter/decrypter class
        AESFileEncripter = new AESEncrypter(key);

        /** fin inicio del encriptador*/
    }
    /**
     * create a new pipe adv, publish it for 2 minut network time,
     * sleep for 3 minutes, then repeat
     */
    public void start() {
        ThreadNotifyShared t = new ThreadNotifyShared(discovery, this.peerName,  this, llaveEntrePeers);
        ThreadListeningRequestFile tRF= new ThreadListeningRequestFile(discovery);
        t.start();
        tRF.start();
    }

    public void buscarArchivos(String search, String tBusqueda, InterfacePeer aThis) throws IOException {
        inteface=aThis;
        long waittime = 5 * 1000L;
        tipoBusqueda = tBusqueda;
        busqueda = search;
        //listaTemp.clear();
        try {

            // look for any peer
            if (tipoBusqueda.equals("Tamano")) {
                tamanoBusqueda= Long.parseLong(search);
                discovery.getRemoteAdvertisements(
                        // no specific peer (propagate)
                        null,
                        // Adv type
                        DiscoveryService.ADV,
                        // Attribute = name
                        "name",
                        // Value = the tutorial
                        "file",
                        // 1000 advertisement response is all we are looking for
                        1000,
                        // no query specific listener. we are using a global listener
                        null);
            } else if (tipoBusqueda.equals("PalabrasClave")) {
                 
                 discovery.getRemoteAdvertisements(
                        // no specific peer (propagate)
                        null,
                        // Adv type
                        DiscoveryService.ADV,
                        // Attribute = name
                        "name",
                        // Value = the tutorial
                        "file",
                        // 1000 advertisement response is all we are looking for
                        1000,
                        // no query specific listener. we are using a global listener
                        null);
            } 
            else {
                discovery.getRemoteAdvertisements(
                        // no specific peer (propagate)
                        null,
                        // Adv type
                        DiscoveryService.ADV,
                        // Attribute = name
                        "nombreArchivo",
                        // Value = the tutorial
                        busqueda,
                        // 1000 advertisement response is all we are looking for
                        1000,
                        // no query specific listener. we are using a global listener
                        null);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public void ClasificarBusqueda(AdvertisementSharedFiles adv) {
        
                        if (!listaTemp.containsKey(adv.getOSName())) {
                            listaTemp.put(adv.getOSName(), adv);
                        }
                        idpeer = adv.getID();

                        if (tipoBusqueda.equals("Nombre")) {
                             System.out.println("Entro Nombre: "+listaTemp.size());
                             listaArchivosBusqueda = darBusquedaNombre(listaTemp, busqueda);
                             inteface.actualizarListaArchivos(listaArchivosBusqueda);
                        }
                        if (tipoBusqueda.equals("Tamano")) {
                            System.out.println("Entro Tamano: "+listaTemp.size());
                            inteface.actualizarListaArchivos(darBusquedaTamano(listaTemp));
                        }
                        if (tipoBusqueda.equals("PalabrasClave")) {
                            System.out.println("Entro PalabrasClave: " +listaTemp.size());
                            listaArchivosBusqueda = darBusquedaPalabrasClave(listaTemp);
                            inteface.actualizarListaArchivos(listaArchivosBusqueda);
                        }
    }

    public void descargarArchivo(String nombreArchivo, String tamanoArchivo, AdvertisementSharedFiles adv) {
        try {
            JxtaSocket socketServidor = conectarse(adv);
            System.out.println("Conectado a "+ socketServidor.getRemoteSocketAddress()+" "+socketServidor.getLocalAddress());
            OutputStream clienteOut = socketServidor.getOutputStream();
            InputStream clienteIn = socketServidor.getInputStream();
            PrintWriter pw = new PrintWriter(clienteOut, true);
            pw.println("DESCARGAR_ARCHIVO;" + nombreArchivo);

            long tamArchivo = Long.parseLong(tamanoArchivo);
            try {
                File nuevoArchivo = new File("../temp/Descargas/" + nombreArchivo);

                if (!nuevoArchivo.getParentFile().exists()) {
                    nuevoArchivo.getParentFile().mkdirs();
                }
                FileOutputStream fos = new FileOutputStream(nuevoArchivo);
                long tamPaquetes = TAM_PAQUETES;
                long numeroPaquetes = tamArchivo / tamPaquetes;
                if (tamArchivo < tamPaquetes) {
                    byte[] menor = new byte[(int) tamArchivo];
                    clienteIn.read(menor);
                    fos.write(menor);
                } else {
                    for (int i = 0; i < numeroPaquetes; i++) {
                        byte[] paq = new byte[(int) tamPaquetes];
                        clienteIn.read(paq);
                        fos.write(paq);
                    }
                    long loQueFalta = tamArchivo - (numeroPaquetes * tamPaquetes);
                    if (loQueFalta > 0) {
                        byte[] paq = new byte[(int) loQueFalta];
                        clienteIn.read(paq);
                        fos.write(paq);
                    }
                }


                InfoArchivo archivo= new InfoArchivo(nombreArchivo,nuevoArchivo.getCanonicalPath(), true);


                java.util.Date fecha = new Date();
                SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy - KK:mm a");
                String fechaDescargaS = sdf.format(fecha);
                archivo.setFechaDescargado(fechaDescargaS);
                archivo.setFechaCreacion(adv.getfechaCreacion());
                listaDescargados.add(archivo);
                if (!listaTemp.containsKey(adv.getOSName())) {
                            listaTemp.put(adv.getOSName(), adv);
                }

                fos.close();
                desconectarse(socketServidor);

            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        } catch (IOException ex) {
            Logger.getLogger(Peer.class.getName()).log(Level.SEVERE, null, ex);
        }
        
    }

    public void compartirFile(File archivoACompartir ,String[] listaPalabras) throws IOException {
        
        File nuevoArchivo = new File("../temp/Compartidos/" + archivoACompartir.getName());
        InputStream clienteIn = new FileInputStream(archivoACompartir);
        if (!nuevoArchivo.getParentFile().exists()) {
           nuevoArchivo.getParentFile().mkdirs();
        }
        long tamArchivo = archivoACompartir.length();
        FileOutputStream fos = new FileOutputStream(nuevoArchivo);
        long tamPaquetes = TAM_PAQUETES;
        long numeroPaquetes = tamArchivo / tamPaquetes;
        if (tamArchivo < tamPaquetes) {
            byte[] menor = new byte[(int) tamArchivo];
            clienteIn.read(menor);
            fos.write(menor);
        } else {
            for (int i = 0; i < numeroPaquetes; i++) {
                byte[] paq = new byte[(int) tamPaquetes];
                clienteIn.read(paq);
                fos.write(paq);
            }
            long loQueFalta = tamArchivo - (numeroPaquetes * tamPaquetes);
            if (loQueFalta > 0) {
                byte[] paq = new byte[(int) loQueFalta];
                clienteIn.read(paq);
                fos.write(paq);
            }
        }
        InfoArchivo info = new InfoArchivo(nuevoArchivo.getName(),nuevoArchivo.getPath(), false);
        java.util.Date fecha = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy - KK:mm a");
        String fechaCreacion = sdf.format(fecha);

        info.setFechaCreacion(fechaCreacion);
        info.setPalabraClave1(listaPalabras[0]);
        info.setPalabraClave2(listaPalabras[1]);
        info.setPalabraClave3(listaPalabras[2]);
        listaCompartidos.add(info);
        fos.close();

        
        
    }

    /**
     * Stops the platform
     */
    public void stop() {
        // Stop JXTA
        manager.stopNetwork();
    }

    public HashMap<String, AdvertisementSharedFiles> darArchivosBusqueda() {
        return listaArchivosBusqueda;
    }

    private JxtaSocket conectarse(AdvertisementSharedFiles adv ) throws IOException {
        pipeAdv = createSocketAdvertisement();
        long start = System.currentTimeMillis();
        System.out.println("Connecting to the network");

        PeerID peerID=null;
        try {
            peerID = (PeerID) IDFactory.fromURI(new URI(adv.getID().toString()));
        } catch (URISyntaxException ex) {
            Logger.getLogger(Peer.class.getName()).log(Level.SEVERE, null, ex);
        }
        JxtaSocket socket = new JxtaSocket(netPeerGroup,
                // no specific peerid
                peerID,
                pipeAdv,
                // connection timeout: 5 seconds
                6000,
                // reliable connection
                true);

        // get the socket output stream
        return socket;
    }

    private void desconectarse(JxtaSocket socketServidor) {
        try {
            socketServidor.close();
        } catch (IOException ex) {
         }
    }

    public PipeAdvertisement createSocketAdvertisement() {
       PipeID socketID = null;

        try {
            socketID = (PipeID) IDFactory.fromURI(new URI(SOCKETIDSTR));
        } catch (URISyntaxException use) {
            use.printStackTrace();
        }
        PipeAdvertisement advertisement = (PipeAdvertisement) AdvertisementFactory.newAdvertisement(PipeAdvertisement.getAdvertisementType());

        advertisement.setPipeID(socketID);
        advertisement.setType(PipeService.UnicastType);
        advertisement.setName("Peer to peer socket");
        System.out.println("Saliendo del socket server");
        return advertisement;
    }

    public ArrayList< AdvertisementSharedFiles> darBusquedaTamano(HashMap<String, AdvertisementSharedFiles> hashAdvertisementsArchivos) {
       
         HashMap<String, AdvertisementSharedFiles> listaArchivosCoincidentes = new HashMap<String, AdvertisementSharedFiles>();
        Collection<AdvertisementSharedFiles> advertisementsArchivos = hashAdvertisementsArchivos.values();
        for (AdvertisementSharedFiles advertisementArchivo : advertisementsArchivos) {
            Long tamArchivoAProbar = Long.parseLong(advertisementArchivo.getOStamano());
            int range =1000*1000;
            Long limInferior = tamArchivoAProbar - range;
            Long limSuperior = tamArchivoAProbar + range;
            if (tamanoBusqueda> limInferior && tamanoBusqueda < limSuperior) {
                listaArchivosCoincidentes.put(advertisementArchivo.getOSName(), advertisementArchivo);
            }
        }
        return ordenar(listaArchivosCoincidentes);
        //return listaArchivosCoincidentes;
    }
    private ArrayList<AdvertisementSharedFiles>  ordenar(HashMap<String, AdvertisementSharedFiles> lista){
        ArrayList<AdvertisementSharedFiles> listTempORD= new ArrayList<AdvertisementSharedFiles>();
         Collection<AdvertisementSharedFiles> advertisementsArchivos = lista.values();
        for (AdvertisementSharedFiles adv : advertisementsArchivos) {
            
            Long t1 = Long.parseLong(adv.getOStamano());
            Long cercania1=(t1-tamanoBusqueda)/t1;
            if(listTempORD.isEmpty()) {
                listTempORD.add(adv);
            }
            else{
                  for (AdvertisementSharedFiles advTemp : listTempORD) {
                            Long t2 = Long.parseLong(advTemp.getOStamano());
                            Long cercania2=(t2-tamanoBusqueda)/t2;
                            System.out.println("cer1; "+cercania1+"cer2: "+cercania2);
                            if(cercania1>cercania2)
                                {
                                listTempORD.add(adv);
                               }
                        }
                  }
        }
       
        return listTempORD;
    }
   
    private HashMap<String, AdvertisementSharedFiles> darBusquedaNombre(HashMap<String, AdvertisementSharedFiles> listaTemp, String busqueda) {

            HashMap<String, AdvertisementSharedFiles> listaArchivosCoincidentes = new HashMap<String, AdvertisementSharedFiles>();
            Collection<AdvertisementSharedFiles> advertisementsArchivos = listaTemp.values();
            for (AdvertisementSharedFiles advertisementArchivo : advertisementsArchivos) {
                if(busqueda.equalsIgnoreCase(advertisementArchivo.getOSName()))

                 {
                    listaArchivosCoincidentes.put(busqueda, advertisementArchivo);
                }

            }
            return listaArchivosCoincidentes;
    }

    private HashMap<String, AdvertisementSharedFiles> darBusquedaPalabrasClave(HashMap<String, AdvertisementSharedFiles> listaTemp) {
            HashMap<String, AdvertisementSharedFiles> listaArchivosCoincidentes = new HashMap<String, AdvertisementSharedFiles>();
            Collection<AdvertisementSharedFiles> advertisementsArchivos = listaTemp.values();
            System.out.println("Tamaño Archivos Buscados"+ listaTemp.size());

            for (AdvertisementSharedFiles adv : advertisementsArchivos) {



                        if(busqueda.equalsIgnoreCase(encriptador.desencriptarMensaje(llaveEntrePeers,adv.getPalabraClave1() )) ||
                           busqueda.equalsIgnoreCase(encriptador.desencriptarMensaje(llaveEntrePeers,adv.getPalabraClave2())) ||
                           busqueda.equalsIgnoreCase(encriptador.desencriptarMensaje(llaveEntrePeers,adv.getPalabraClave3()))) {
                            listaArchivosCoincidentes.put(busqueda, adv);

                 }
            }
            return listaArchivosCoincidentes;
    }
    public String[] darPalabrasClaveArchivoTAl(String nameFile){
        String[] lista= new String[3];

        for (int i = 0; i < listaCompartidos.size(); i++) {
            InfoArchivo infoArchivo = listaCompartidos.get(i);
            if(infoArchivo.getNombreArchivo().equalsIgnoreCase(nameFile)){
                lista[0]=infoArchivo.getPalabraClave1();
                lista[1]=infoArchivo.getPalabraClave2();
                lista[2]=infoArchivo.getPalabraClave3();
                return lista;
            }
        }
        return null;
    }
     public String darFechaCreacionArchivoTAl(String nameFile){

        for (int i = 0; i < listaCompartidos.size(); i++) {
            InfoArchivo infoArchivo = listaCompartidos.get(i);
             System.out.println("nombre A;"+nameFile+"nombre B;"+infoArchivo.getNombreArchivo()+"fehca:"+infoArchivo.getFechaCreacion());

            if(infoArchivo.getNombreArchivo().equalsIgnoreCase(nameFile)){
                 System.out.println("nombre A;"+nameFile+"nombre B;"+infoArchivo.getNombreArchivo()+"fehca:"+infoArchivo.getFechaCreacion());
                return infoArchivo.getFechaCreacion();
            }
        }
        return null;
    }
    public void adicionarListaTemp(AdvertisementSharedFiles adver ){
                if (!listaTemp.containsKey(adver.getOSName())) {
                    listaTemp.put(adver.getOSName(), adver);
                }
    }
    public InfoArchivo darInfoArchivoDescargado(String nameFile){
        for (int i = 0; i < listaDescargados.size(); i++) {
            InfoArchivo infoArchivo = listaDescargados.get(i);
            if(infoArchivo.getNombreArchivo().equalsIgnoreCase(nameFile)){
                return infoArchivo;
            }
        }
        return null;
    }
    public InfoArchivo darInfoArchivoCompartido(String nameFile){
        for (int i = 0; i < listaCompartidos.size(); i++) {
            InfoArchivo infoArchivo = listaCompartidos.get(i);
            if(infoArchivo.getNombreArchivo().equalsIgnoreCase(nameFile)){
                return infoArchivo;
            }
        }
        return null;
    }
    public PeerID darPeerID() {
            return peerID;
        }
    public void peticionAbrirArchivo(InfoArchivo archivo) {
                variableGlobal= true;
        try {
                long lifetime = 60 * 10 * 1000L;
                long expiration = 60 * 10 * 1000L;
                JOptionPane.showMessageDialog(null, "Enviando la solitud de trabajo para en el Archivo: "+archivo.nombreArchivo, "Solicitud para abrir archivo", JOptionPane.INFORMATION_MESSAGE);
                AdvertisementAskForFile aa = new AdvertisementAskForFile();
                aa.setType(PipeService.UnicastType);
                aa.setID(darPeerID());
                aa.setNamePeer(peerName);
                aa.setNombreArchivo(archivo.nombreArchivo);
                aa.setTipoAnuncio("anuncio");
                java.util.Date fecha = new Date();
                aa.setFechaCreacion(""+fecha.toString());
                discovery.publish(aa, lifetime, expiration);

                threadEsperaArbrirArchivo= new TreadWaitingAccessFile(this, archivo);
                threadEsperaArbrirArchivo.run();

        } catch (IOException ex) {
            Logger.getLogger(Peer.class.getName()).log(Level.SEVERE, null, ex);
        }

       //esperar solicitudes de respuesta

    }
     public void abrirArchivo(InfoArchivo archivo) {

             if (archivo.rutaArchivo.endsWith(".mp3")||
                archivo.rutaArchivo.endsWith(".wav")||
                archivo.rutaArchivo.endsWith(".wma")) {
                File arch = new File(archivo.rutaArchivo);
            {
                FileInputStream fis = null;
                try {
                    fis = new FileInputStream(arch);
                    BufferedInputStream bis = new BufferedInputStream(fis);
                    Player player = new Player(bis);
                    player.play();
                } catch (FileNotFoundException ex) {
                    Logger.getLogger(Peer.class.getName()).log(Level.SEVERE, null, ex);
                } catch (JavaLayerException ex) {
                    Logger.getLogger(Peer.class.getName()).log(Level.SEVERE, null, ex);
                } finally {
                    try {
                        fis.close();
                    } catch (IOException ex) {
                        Logger.getLogger(Peer.class.getName()).log(Level.SEVERE, null, ex);
                    }} }}
            else{
               try {
                            Desktop.getDesktop().open(new File(archivo.rutaArchivo));
                        }    catch (IOException ex) {
                        JOptionPane.showMessageDialog(null, "No hay un programa asociado para abrir este tipo de archivo"+archivo.rutaArchivo, "Error Abriendo archivo", JOptionPane.ERROR_MESSAGE);
                }}

     }

    public boolean verificarArchivoUso(String nombreArchivo) {
        InfoArchivo archivo=    darInfoArchivo(nombreArchivo);
        if(archivo==null){
            System.out.println("NO LO TENGO");
            return false;
        }else{
            try {
                File f = new File(darInfoArchivo(nombreArchivo).getRutaArchivo());
                 File f1 = new File(f.getCanonicalPath());
                 System.out.println("LO TENGO: ");
                RandomAccessFile r =new RandomAccessFile(f1, "rw");
                System.out.println("No Usando");
                     return false;
                 
            } catch (IOException ex) {
                 System.out.println("Usando");
                return true;
            }
        }
    }
    public InfoArchivo darInfoArchivo(String name){
                 if(darInfoArchivoDescargado(name)!=null){
                     return darInfoArchivoDescargado(name);
                 }
                 else if(darInfoArchivoCompartido(name)!=null){
                             return darInfoArchivoCompartido(name);
                 }
                 else
                     return null;
      }

    public String darPeerName() {
        return peerName;
    }

     public boolean VariableGlobal() {
       return variableGlobal;
    }
     public void cambiarVariableGlobal(boolean b) {
      variableGlobal=b;
    }

     /**
      * Guardar el estado de un nodo en un archivo XML
      */
    public void guardarEstadoNodo() {

        this.guardarEstadoNodoXML.escribirTxt(this.numEstado,this.peerName,this.listaCompartidos, this.listaDescargados);
        numEstado++;
        this.notificarGuardarEstado();
    }
    public void guardarEstadoNodoPorNotificacion() {

        this.guardarEstadoNodoXML.escribirTxt(this.numEstado,this.peerName,this.listaCompartidos, this.listaDescargados);
        numEstado++;
    }

    /**
     * envia un mensaje para que los otros nodos
     * conectados al sistema guarden su estado
     */
    public void notificarGuardarEstado(){
        try {
                long lifetime = 60 * 1 * 1000L;
                long expiration = 60 * 1 * 1000L;
                 AdvertisementGuardarEstadoGlobal aa = new AdvertisementGuardarEstadoGlobal();
                aa.setType(PipeService.UnicastType);
                aa.setID(darPeerID());
                aa.setNombrePeer(peerName);
                aa.setTipoAnuncio("Guardar");
                java.util.Date fecha = new Date();
                aa.setFechaCreacion(""+fecha.toString());
                discovery.publish(aa, lifetime, expiration);

                } catch (IOException ex) {
                    Logger.getLogger(Peer.class.getName()).log(Level.SEVERE, null, ex);
                }
    }
    private void AuthenticatePeer(String peernombre) throws IOException {
        System.out.println("Autenticacion");
        Socket sockServidor = conectarConServidor();
        OutputStream clienteOut = sockServidor.getOutputStream();
        InputStream clienteIn = sockServidor.getInputStream();

        PrintWriter p = new PrintWriter(clienteOut, true);
        String msnSolCertif = "SOLICITO_CERTIFICADO;" + peernombre;
        p.println(msnSolCertif);
        clienteOut.flush();
        BufferedReader br = new BufferedReader(new InputStreamReader(sockServidor.getInputStream()));
        //Formato de resultados RESULTADO: positivo o negativo
        String cadenaResultados = br.readLine();
        if (cadenaResultados.startsWith("CERTIFICADO_EXISTE")) {
            System.out.println("CERTIFICADO_EXISTE");
            String sTamArchivo = cadenaResultados.split(";")[1];
            long tamArchivo = Long.parseLong(sTamArchivo);
            File archivoLlaves = new File("../temp/Certificados/" + peernombre + ".p12");
            if (!archivoLlaves.getParentFile().exists()) {
                archivoLlaves.getParentFile().mkdirs();
            }
            FileOutputStream fos = new FileOutputStream(archivoLlaves);
            long tamPaquetes = TAM_PAQUETES;
            long numeroPaquetes = tamArchivo / tamPaquetes;
            if (tamArchivo < tamPaquetes) {
                byte[] menor = new byte[(int) tamArchivo];
                clienteIn.read(menor);
                fos.write(menor);
            } else {
                for (int i = 0; i < numeroPaquetes; i++) {
                    byte[] paq = new byte[(int) tamPaquetes];
                    clienteIn.read(paq);
                    fos.write(paq);
                }
                long loQueFalta = tamArchivo - (numeroPaquetes * tamPaquetes);
                if (loQueFalta > 0) {
                    byte[] paq = new byte[(int) loQueFalta];
                    clienteIn.read(paq);
                    fos.write(paq);
                }
            }
            procesarLlaves(archivoLlaves);
        } else if (cadenaResultados.startsWith("NOEXISTE_CERTIFICADO")) {
            JOptionPane.showMessageDialog(null,"Usted no tiene permisos para acceder a este grupo","Error ingreso",JOptionPane.ERROR_MESSAGE);
            System.exit(1);
        }
        sockServidor.close();
    }
    private Socket conectarConServidor() {
        //String ipServidor = "192.168.1.101";
       // String ipServidor = "192.168.1.114";
        String ipServidor = "localhost";
        try {
            Socket socketServidor = new Socket(ipServidor, PUERTO);
            return socketServidor;
        } catch (UnknownHostException ex) {
            Logger.getLogger(Peer.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Peer.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }
    private void procesarLlaves(File archivoLlaves) {
        
        java.security.KeyStore ks;
        try {
            ks = java.security.KeyStore.getInstance("PKCS12");
            ks.load(new java.io.FileInputStream("../temp/Certificados/" + peerName + ".p12"),"password".toCharArray());
            char[] key = "password".toCharArray();
            Certificate cer=ks.getCertificate("alias");
            Key publickey=cer.getPublicKey();
            Key privatekey=ks.getKey("alias", key);
            //System.out.println( " Public KEY:"+publickey+"Private:"+privatekey);

        } catch (UnrecoverableKeyException ex) {
            Logger.getLogger(Peer.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Peer.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(Peer.class.getName()).log(Level.SEVERE, null, ex);
        } catch (CertificateException ex) {
            Logger.getLogger(Peer.class.getName()).log(Level.SEVERE, null, ex);
        } catch (KeyStoreException ex) {
            Logger.getLogger(Peer.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    /**
     * Comprime un archivo
     */
    public void comprimirArchivo(String nombreArchivo)
    {

        // These are the files to include in the ZIP file
        String[] filenames = new String[]{"../temp/Compartidos/" + nombreArchivo};

// Create a buffer for reading the files
        byte[] buf = new byte[1024];

        try {
            // Create the ZIP file
            String outFilename = "../temp/Compartidos/" + nombreArchivo + ".zip";
            System.out.println(outFilename);
            ZipOutputStream out = new ZipOutputStream(new FileOutputStream(outFilename));

            // Compress the files
            for (int i = 0; i < filenames.length; i++) {
                FileInputStream in = new FileInputStream(filenames[i]);

                // Add ZIP entry to output stream.
                out.putNextEntry(new ZipEntry(filenames[i]));

                // Transfer bytes from the file to the ZIP file
                int len;
                while ((len = in.read(buf)) > 0) {
                    out.write(buf, 0, len);
                }

                // Complete the entry
                out.closeEntry();
                in.close();
            }

            // Complete the ZIP file
            out.close();
        } catch (IOException e) {
        }

    }

    public void encriptarAES(String arch)
    {
        String outFilename = "../temp/Compartidos/" + arch;
        try {
            AESFileEncripter.encrypt(new FileInputStream(outFilename), new FileOutputStream(outFilename+".enc"));
        } catch (FileNotFoundException ex) {
            Logger.getLogger(Peer.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void DesEncriptarAES(String arch)
    {
        String outFilename = "../temp/Compartidos/" + arch;
        try {
            AESFileEncripter.decrypt(new FileInputStream(outFilename), new FileOutputStream(outFilename.substring(0, outFilename.length()-4)));
            } catch (FileNotFoundException ex) {
            Logger.getLogger(Peer.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

}
